package com.itaming.lycheeframework.support.cipher.asymmetric;

import com.itaming.lycheeframework.support.cipher.CipherConstant;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
import org.bouncycastle.jce.spec.ECPrivateKeySpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.spec.KeySpec;

/**
 * SM2加密器
 *
 * @author A.Ming
 */
public class Sm2Encryptor extends AbstractAsymmetricEncryptor {

    /**
     * 获取KeyFactory实例
     *
     * @return
     */
    @Override
    protected KeyFactory getKeyFactory() throws NoSuchAlgorithmException {
        return KeyFactory.getInstance(CipherConstant.ALGORITHM_EC);
    }

    /**
     * 获取公钥KeySpec
     *
     * @param publicKey 公钥
     * @return 公钥KeySpec
     */
    @Override
    protected KeySpec getPublicKeySpec(byte[] publicKey) {
        ECNamedCurveParameterSpec parameterSpec = getSm2CurveParameterSpec();
        ECPoint ecPoint = parameterSpec.getCurve().decodePoint(publicKey);
        return new ECPublicKeySpec(ecPoint, parameterSpec);

    }

    /**
     * 获取私钥KeySpec
     *
     * @param privateKey 私钥
     * @return 私钥KeySpec
     */
    @Override
    protected KeySpec getPrivateKeySpec(byte[] privateKey) {
        ECNamedCurveParameterSpec parameterSpec = getSm2CurveParameterSpec();
        BigInteger privateKeyBigInteger = new BigInteger(1, privateKey);
        return new ECPrivateKeySpec(privateKeyBigInteger, parameterSpec);
    }

    /**
     * 获取SM2椭圆曲线参数
     *
     * @return 椭圆曲线参数
     */
    private static ECNamedCurveParameterSpec getSm2CurveParameterSpec() {
        return ECNamedCurveTable.getParameterSpec(CipherConstant.SM2_CURVE_NAME);
    }

}
